////////////////////////////////////////////////////////////////////////////////
// Copyright 2006 CORE Solutions Limited
// All rights reserved.
// PROPRIETARY AND CONFIDENTIAL INFORMATION.
// Use is subject to license terms.
//
// FUNCTION ID      :   SimpleMaintStyleAction
// AUTHOR           :    
// DATE CREATE      :   
// DESCRIPTION      :   
//                  :   
//                  :   
//                  :   
//
// MODIFICATION HISTORY:
// DATE         AUTHOR          VERSION NO.         COMMENT
// -----------  --------------  ------------------  -------------------
// 2006/04/10   Ric Yik         1.0                 BugZilla #5218
// 2006/05/17   Ric Yik         1.0                 BugZilla #5796
// 2006/06/23   Ric Yik         1.0                 BugZilla #5535
//
////////////////////////////////////////////////////////////////////////////////

package com.erp.framework.controller.action;

import java.beans.PropertyDescriptor;
import java.io.ByteArrayOutputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import com.erp.framework.SimpleConstants;
import com.erp.framework.controller.form.MultiRow;
import com.erp.framework.controller.form.SimpleCoreForm;
import com.erp.framework.controller.form.SimpleMaintStyleForm;
import com.erp.framework.exceptions.NotEqualException;
import com.erp.framework.exceptions.NullValueException;
import com.erp.framework.model.delegate.SimpleSearchMaintStyleDelegate;
import com.erp.framework.model.pk.SimpleBasePk;
import com.erp.framework.model.schema.TableSchema;
import com.erp.framework.model.vo.ChildList;
import com.erp.framework.model.vo.SimpleBaseVo;
import com.erp.framework.util.BeanUtil;
import com.erp.framework.util.CommonUtil;
import com.erp.framework.util.CopyUtil;
import com.erp.framework.util.logger.Logger;
import com.erp.framework.util.user.User;
import com.lowagie.text.Document;
import com.lowagie.text.pdf.PdfWriter;

public abstract class SimpleMaintStyleAction extends SimpleCoreAction {

    ////////////////////////////////////////////////////////////////////////////////
    // ABSTRACT METHODS THAT NEED BE IMPLEMENTED BY SUB-CLASSES
    ////////////////////////////////////////////////////////////////////////////////

    protected abstract String getModuleName(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response);

    protected abstract String getFunctionId();
       
    protected abstract String getMasterFormSessionName();
        
    protected abstract Class getMasterFormClass();
    
    protected abstract Class getMasterVOClass();
           
	protected abstract Class[] getChildRowClass();

    protected abstract String[] getFolderChildIdxMapping();
   
    protected abstract SimpleBasePk getPk(ActionForm formIn, HttpServletRequest request);
    
    protected abstract void setFormType(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response, ActionErrors errors);

    protected Class getMasterPrintFormPdfActionClass(){return null;}
    
    protected String getPrintFormPdfFileName(ActionForm formIn){return null;}
    
    protected void setDocNoToSession(ActionForm formIn, HttpServletRequest request){};
     
    public ActionForward processActionPrintFormPdf(ActionMapping mapping, ActionForm formIn, 
            HttpServletRequest request, HttpServletResponse response, ActionErrors errors) {                
                
        try {
        	HttpSession session = request.getSession(false);
        	SimpleMaintStyleForm form = (SimpleMaintStyleForm) getMasterFormClass().newInstance();
        	
        	response.setContentType("application/pdf");
			response.setHeader("Content-Disposition", "attachment;filename=\"" + getPrintFormPdfFileName(formIn) + ".pdf\"");
			response.setStatus(HttpServletResponse.SC_OK);			 
			
			setDocNoToSession(formIn, request);
			
//			SimpleBasePrintFormPdfAction printAction = (SimpleBasePrintFormPdfAction) getMasterPrintFormPdfActionClass().getConstructor(
//					new Class[] {ActionForm.class} ).newInstance( new Object[] {form});
			SimpleBasePrintFormPdfAction printAction = (SimpleBasePrintFormPdfAction) getMasterPrintFormPdfActionClass().newInstance();
			
	        Document document = printAction.getPrintFormDefaultDocument();
	        ByteArrayOutputStream baos = new ByteArrayOutputStream();
	        PdfWriter writer = PdfWriter.getInstance(document, baos);
	        printAction.setPdfDocPassword(writer, session, null);
			 
	        if(printAction.needBaos()){	        	
	        	document = printAction.preparePdfDoc(mapping, formIn, request, response, servlet.getServletContext(), writer, document, baos);
	        } else {
	        	document = printAction.preparePdfDoc(mapping, formIn, request, response, servlet.getServletContext(), writer, document);
	        }
	        
	        SimpleBasePrintFormPdfAction.outputByteArrayStream(request, response, session, baos);
	        
	        if(document.isOpen()){
	        	document.close();
	        }
	        baos.close();
	        writer.close();
	        
        } catch (Exception e) {
            Logger.logExceptions(this, e);
            response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED);
        }
        
        return null;
    }
    
    ////////////////////////////////////////////////////////////////////////////////
    // END OF ABSTRACT METHODS
    ////////////////////////////////////////////////////////////////////////////////

    
    ////////////////////////////////////////////////////////////////////////////////
    // OPTIONAL METHODS THAT CAN BE OVERWRITTEN BY SUB-CLASSES
    ////////////////////////////////////////////////////////////////////////////////

    //old
    /**
     * @ddeprecated
     */
	protected void initAction(ActionMapping mapping, ActionForm formIn, HttpServletRequest request, HttpServletResponse response) {
    }

    protected void initAction(ActionMapping mapping, ActionForm formIn, HttpServletRequest request, 
            HttpServletResponse response, ActionErrors errors) {
        initAction(mapping, formIn, request, response); //to support the old way
        
        
    }

    protected SimpleMaintStyleForm createMasterForm(ActionMapping mapping, SimpleMaintStyleForm originalForm, HttpServletRequest request,
            HttpServletResponse response, ActionErrors errors) throws Exception {
        SimpleMaintStyleForm result = (SimpleMaintStyleForm) getMasterFormClass().newInstance();
        result.setErrMsgMap(originalForm.getErrMsgMap());
        result.setSysLangCode((String) request.getSession(false).getAttribute(SESSION_SYSTEM_LANG));
        result.setMenuObjectList(originalForm.getMenuObjectList());        
        result.setIsReadOnly(originalForm.getIsReadOnly());
        result.setRoCaller(originalForm.getRoCaller());
        result.setFormType(originalForm.getFormType());
        result.setEditType(originalForm.getEditType());
        this.afterCreateMasterForm(mapping, originalForm, result, request, response, errors);
        return result;
    }

    protected void afterCreateMasterForm(ActionMapping mapping, SimpleMaintStyleForm originalForm, SimpleMaintStyleForm newMasterForm, HttpServletRequest request,
            HttpServletResponse response, ActionErrors errors) throws Exception {
    }
  
    protected void initForm(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response, ActionErrors errors) {

        ActionForward actionForward = null;
        try {
            actionForward = new ActionForward(mapping.getInput());
            SimpleMaintStyleForm form = (SimpleMaintStyleForm) formIn;
            HttpSession session = request.getSession(false);
            removeMasterMaintDelegate(session);
            form = (SimpleMaintStyleForm) this.createMasterForm(mapping, form, request, response, errors);

            initPage(mapping, form, request, response, errors);

            session.setAttribute(getMasterFormSessionName(), form);
        } catch (Exception e) {
            errors.add(ActionErrors.GLOBAL_ERROR, new ActionError("exception.error", e.getMessage()));
            Logger.logExceptions(this, e);
        }
    }

    protected void initPage(ActionMapping mapping, ActionForm formIn, HttpServletRequest request, HttpServletResponse response,
            ActionErrors errors) {

        try {
            SimpleMaintStyleForm form = (SimpleMaintStyleForm) formIn;
            Class[] childRowClass = getChildRowClass();
            if (childRowClass != null) {
                int count = childRowClass.length;
                for (int i = 0; i < count; i++) {
                    form.setCurrIdx(i);
                    form.setMultiRowClazz(childRowClass[i]);
                }
            }

            setDefaultFolderIdx(mapping, form, request, response, errors);

            processActionChangeFolder(mapping, form, request, response, errors);

            setAccessControl(mapping, form, request, response, errors);
            processRequestAttributes(form, request);
        } catch (Exception e) {
            errors.add(ActionErrors.GLOBAL_ERROR, new ActionError("exception.error", e.getMessage()));
            Logger.logExceptions(this, e);
        }
    }

    protected void beforeCreate(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response, ActionErrors errors) {

    }

    /**
     * @ddeprecated
     * @param mapping
     * @param formIn
     * @param request
     * @param response
     * @param errors
     * 
     * @see SimpleBaseForm.moreValidate(mapping, formIn, request, response, errors);
     */
    protected void otherValidate(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response, ActionErrors errors) {

    }

    protected void beforeSave(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response, ActionErrors errors) {

    }

    protected void afterSave(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response, ActionErrors errors) {

    }

    protected void beforeEdit(ActionMapping mapping, ActionForm formIn, HttpServletRequest request, HttpServletResponse response,
            ActionErrors errors) {

    }

    protected void afterEdit(ActionMapping mapping, ActionForm formIn, HttpServletRequest request, HttpServletResponse response,
            ActionErrors errors) {

    }

    protected void beforeDelete(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response, ActionErrors errors) {

    }

    protected void afterDelete(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response, ActionErrors errors) {

    }
    
    protected void beforeRefresh(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response, ActionErrors errors) {

    }
    
    protected void afterRefresh(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response, ActionErrors errors) {

    }
    
    protected void beforeExit(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response, ActionErrors errors) {

    }
    
    protected void beforeFormToModel(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response, ActionErrors errors, SimpleBaseVo model) {

    }
    
    protected void afterFormToModel(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response, ActionErrors errors, SimpleBaseVo model) {

    }
    
    protected void beforeModelToForm(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response, ActionErrors errors, SimpleBaseVo model) {

    }
    
    protected void afterModelToForm(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response, ActionErrors errors, SimpleBaseVo model) {

    }
    
    protected void processPostCopy(SimpleBaseVo copiedModel, HttpSession session, ActionErrors errors) {
    }
    
    protected void populateForm(SimpleMaintStyleForm form, HashMap params, HttpServletRequest request) {

    }
    
    protected Class getMasterDelegateClass() {

        return SimpleSearchMaintStyleDelegate.class;
    }
    
    protected Class getCopyActionClass() {

        return null;
    }
    
    protected String getSessionSimpleSearchStatus() {

        return SimpleConstants.SESSION_SIMPLE_SEARCH_STATUS;
    }
        
    protected String getSessionSimpleMaintStatus() {

        return SimpleConstants.SESSION_SIMPLE_MAINT_STATUS;
    }

    protected String getSessionSimpleMaintPk() {

        return SimpleConstants.SESSION_SIMPLE_MAINT_PK;
    }

    protected String getSessionSimpleMaintInitModel() {

        return SimpleConstants.SESSION_SIMPLE_MAINT_INIT_MODEL;
    }

    protected String getSessionSimpleMaintEditType() {

        return SimpleConstants.SESSION_SIMPLE_MAINT_EDIT_TYPE;
    }

    protected String getSessionReset() {

        return SimpleConstants.SESSION_SIMPLE_SEARCH_RESET;
    }
    
    protected String getSessionMasterMaintDelegate() {

        return "SESSION_SM_DELEGATE";
    }
        
	protected String getSessionSimpleReadOnly() {

        return SimpleConstants.SESSION_SIMPLE_READ_ONLY;
    }

    protected boolean getKeepSearchResult() {

        return false;
    }
    
    protected SimpleBaseVo getInitialzedModel(ActionForm form, User editingUser) {

        return null;
    }
    
    ////////////////////////////////////////////////////////////////////////////////
    // END OF OPTIONAL METHODS
    ////////////////////////////////////////////////////////////////////////////////

    
    ////////////////////////////////////////////////////////////////////////////////
    // LOGICAL AND BUSINESS METHODS
    ////////////////////////////////////////////////////////////////////////////////

    protected ActionForward handlePageEvent(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response, ActionErrors errors) {

        return null;
    }
    
    protected ActionForward processOtherStatus(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response, ActionErrors errors, String rb_status) {

        ActionForward actionForward = new ActionForward(mapping.getInput());

        return actionForward;
    }

    protected void beforeTry(ActionMapping mapping, ActionForm formIn, HttpServletRequest request, HttpServletResponse response) {
        try {
            SimpleMaintStyleForm form = null;
            HttpSession session = request.getSession(false);
            if (session != null) form = (SimpleMaintStyleForm) session.getAttribute(this.getMasterFormSessionName());
            if (form == null) form = (SimpleMaintStyleForm) formIn;
            if (form != null) {
                form.setOriginalIdx(form.getCurrIdx());
                if (!CommonUtil.isEmpty(form.getActionIdx())) {
                    try {
                        form.setCurrIdx(Integer.parseInt(form.getActionIdx()));
                    } catch (Exception e) {
                        Logger.logExceptions(this, e);
                    }
                }
            }
        } catch (Exception e) {
            Logger.log(this, e.getMessage());
        }
    }

    protected void onFinally(ActionMapping mapping, ActionForm formIn, HttpServletRequest request, HttpServletResponse response) {
        SimpleMaintStyleForm form = null;
        try {
            HttpSession session = request.getSession(false);
            if (session != null) form = (SimpleMaintStyleForm) session.getAttribute(this.getMasterFormSessionName());
            if (form == null) form = (SimpleMaintStyleForm) formIn;
            if (form != null) {
                if (!CommonUtil.isEmpty(form.getActionIdx())) {
                    form.setCurrIdx(form.getOriginalIdx());
                }
            }
        } catch (Exception e) {
            Logger.log(this, e.getMessage());
        } finally {
            if (form != null) form.setActionIdx("");
        }
    }

    public ActionForward otherExecute(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response) throws ServletException {
        
        HttpSession session = request.getSession(false);
        ActionForward actionForward = new ActionForward(mapping.getInput());
        ActionErrors errors = new CustomActionErrors(new ActionErrors());
        SimpleMaintStyleForm form = (SimpleMaintStyleForm) formIn;
        //initAction(mapping, formIn, request, response); //old way
        initAction(mapping, form, request, response, errors); //new way
        String action = form.getPageEvent();
        action = CommonUtil.isEmpty(action) ? "" : action.trim();        

        String rb_status = CommonUtil.nullToString((String) session.getAttribute(getSessionSimpleMaintStatus()));
        session.removeAttribute(getSessionSimpleMaintStatus());

        Logger.debug(this, "otherExcute(), action = " + action + ", status=[" + rb_status + "]");

        populateIsDelete(form, request);
        form.getFinalRows();

        setFormType(mapping, form, request, response, errors);
                
        if (!isHandled(request) && !rb_status.equals("")) {
            Logger.all(this, "otherExecute(),processStatus,action=" + action);
            setHandled(request);
            actionForward = processStatus(mapping, form, request, response, errors, rb_status);
        } 
        
        Logger.all(this, "otherExecute() isHandled=" + isHandled(request));
        // for initial status
        if (!isHandled(request) && action.length() == 0) {
            setHandled(request);
            initForm(mapping, form, request, response, errors);
            saveToken(request);
        }
        Logger.all(this, "otherExecute() isHandled=" + isHandled(request));
        Logger.all(this, "otherExecute(), before if block, action=[" + action + "]");

//        if (!rb_status.equals("")) {
//	        try{
//	        // Sets the TableSchema
//	            super.copyTsFromVoToForm(mapping, formIn, request, response, null); 
//	            session.setAttribute(getMasterFormSessionName(), formIn);
//	        } catch(Exception e){
//	            Logger.logExceptions(this, e);
//	        }
//        }
            
        if (!isHandled(request) && action.equalsIgnoreCase(ACTION_REFRESH)) {
            Logger.all(this, "otherExecute(),actionRefresh,action=" + action);
            setHandled(request);
            processActionRefresh(mapping, form, request, response, errors);
            saveToken(request);
        } else if (!isHandled(request) && action.equalsIgnoreCase(ACTION_SEARCH)) {
            Logger.all(this, "otherExecute(),actionSearch,action=" + action);
            setHandled(request);
            actionForward = processActionSearch(mapping, form, request, response, errors);
            saveToken(request);
        } else if (!isHandled(request) && action.equalsIgnoreCase(ACTION_DELETE)) {
            Logger.all(this, "otherExecute(),actionDelete,action=" + action);
            setHandled(request);
            actionForward = processActionDelete(mapping, form, request, response, errors, false);
            saveToken(request);
        } else if (!isHandled(request) && action.equalsIgnoreCase(ACTION_PURGE)) {
            Logger.all(this, "otherExecute(),actionPurge,action=" + action);
            setHandled(request);
            actionForward = processActionDelete(mapping, form, request, response, errors, true);
            saveToken(request);            
        } else if (!isHandled(request) && action.equalsIgnoreCase(ACTION_SAVE)) {
            Logger.all(this, "otherExecute(),actionSave,action=" + action);
            setHandled(request);
            actionForward = processActionSave(mapping, form, request, response, errors);
            saveToken(request);
        } else if (!isHandled(request) && action.equalsIgnoreCase(ACTION_EXIT)) {
            Logger.all(this, "otherExecute(),actionExit,action=" + action);
            setHandled(request);
            actionForward = processActionExit(mapping, form, request, response, errors);
            saveToken(request);
        } else if (!isHandled(request) && action.equalsIgnoreCase(ACTION_CREATE)) {
            Logger.all(this, "otherExecute(),actionCreate,action=" + action);
            setHandled(request);
            actionForward = processActionCreate(mapping, form, request, response, errors);
            saveToken(request);
        } else if (!isHandled(request) && action.equalsIgnoreCase(ACTION_CHANGE_FOLDER)) {
            Logger.all(this, "otherExecute(),actionChangeFolder,action=" + action);
            setHandled(request);
            actionForward = processActionChangeFolder(mapping, form, request, response, errors);
            saveToken(request);
        } else if (!isHandled(request) && action.equalsIgnoreCase(ACTION_COPY)) {
            Logger.all(this, "otherExecute(),actionCopy,action=" + action);
            setHandled(request);
            actionForward = processActionCopy(mapping, form, request, response, errors);
            saveToken(request);
        } else if (!isHandled(request) && action.equalsIgnoreCase(ACTION_BACK)) {
            setHandled(request);
            actionForward = processActionBack(mapping, form, request, response, errors);
            saveToken(request);
        } else if (!isHandled(request) && action.equalsIgnoreCase(ACTION_SCROLL_LEFT)) {
            setHandled(request);
            actionForward = processActionScrollLeft(mapping, form, request, response, errors);
            saveToken(request);
        } else if (!isHandled(request) && action.equalsIgnoreCase(ACTION_SCROLL_RIGHT)) {
            setHandled(request);
            actionForward = processActionScrollRight(mapping, form, request, response, errors);
            saveToken(request);
        } else if (!isHandled(request) && action.equalsIgnoreCase(ACTION_SCROLL_TO_FIRST_PAGE)) {
            setHandled(request);
            actionForward = processActionScrollToFirstPage(mapping, form, request, response, errors);
            saveToken(request);
        } else if (!isHandled(request) && action.equalsIgnoreCase(ACTION_SCROLL_TO_LAST_PAGE)) {
            setHandled(request);
            actionForward = processActionScrollToLastPage(mapping, form, request, response, errors);
            saveToken(request);
        } else if (!isHandled(request) && action.equalsIgnoreCase(ACTION_SCROLL_TO)) {
            setHandled(request);
            actionForward = processActionScrollTo(mapping, form, request, response, errors);
            saveToken(request);
        } else if (!isHandled(request) && action.equalsIgnoreCase(ACTION_EDIT)) {
            setHandled(request);
            actionForward = processActionEdit(mapping, form, request, response, errors);
            saveToken(request);       
        } else if (!isHandled(request) && ACTION_RETURN.equalsIgnoreCase(action)) {
            setHandled(request);
            actionForward = processActionReturn(mapping, form, request, response, errors);
            saveToken(request);
        } else if (!isHandled(request) && ACTION_REVISE.equalsIgnoreCase(action)) {
            setHandled(request);
            //form.setIsReadOnly(GENERIC_NO);
            actionForward = processActionRevise(mapping, formIn, request, response, errors);
            saveToken(request);
        } else if (!isHandled(request) && ACTION_PRINT_FORM_PDF.equalsIgnoreCase(action)) {
            setHandled(request);
            actionForward = processActionPrintFormPdf(mapping, form, request, response, errors);
            saveToken(request);              
        } else if (!isHandled(request) && action.length() > 0) {
            Logger.all(this, "otherExecute(), action=" + action);
            actionForward = handlePageEvent(mapping, form, request, response, errors);
            setHandled(request);
        }

        saveErrors(request, errors);
        return actionForward;
    }

    protected ActionForward processStatus(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response, ActionErrors errors, String rb_status) {

        Logger.all(this, "processStatus(), rb_status=" + rb_status);
        if (rb_status.equals(STATUS_CREATE)) {
            return processStatusCreate(mapping, formIn, request, response, errors, rb_status);
        } else if (rb_status.equalsIgnoreCase(STATUS_EDIT) || rb_status.equalsIgnoreCase(STATUS_SAVED_EDIT)) {
            return processStatusEdit(mapping, formIn, request, response, errors, rb_status);
        } else if (rb_status.equalsIgnoreCase(STATUS_COPY)) {
            return processStatusCopy(mapping, formIn, request, response, errors, rb_status);
        } else {
            return processOtherStatus(mapping, formIn, request, response, errors, rb_status);
        }
    }

    protected ActionForward processActionReturn(
            ActionMapping mapping,
            ActionForm formIn,
            HttpServletRequest request,
            HttpServletResponse response,
            ActionErrors errors) {
        ActionForward actionForward = mapping.findForward(FORWARD_GENERIC_SEARCH);
        String destination = getGenericInquiryType();
        
        if (destination == null)
            throw new NullPointerException("Return Destination cannot be null.");
        
        request.setAttribute("type", destination);
        request.setAttribute("pageEvent", "return");
        
        return actionForward;
    }

    protected ActionForward processActionRevise(
            ActionMapping mapping,
            ActionForm formIn,
            HttpServletRequest request,
            HttpServletResponse response,
            ActionErrors errors) {
        ActionForward actionForward = new ActionForward(mapping.getInput());
        SimpleMaintStyleForm form = (SimpleMaintStyleForm) formIn;
        form.setIsReadOnly(GENERIC_NO);
        processActionChangeStatus(mapping, form, request, response, errors);
        processActionOtherRevise(mapping, form, request, response, errors);
        return actionForward;
    }
    
    protected void processActionChangeStatus(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response, ActionErrors errors) {
    	
    }
    
    protected void processActionOtherRevise(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response, ActionErrors errors) {
    	
    }
    
    protected String getGenericInquiryType() {
        throw new UnsupportedOperationException();
    }
    
    protected ActionForward processActionExit(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response, ActionErrors errors) {

        ActionForward actionForward = null;
        try {
        	beforeExit(mapping, formIn, request, response, errors);
        	
            SimpleMaintStyleForm form = (SimpleMaintStyleForm) formIn;
            HttpSession session = request.getSession(false);

            actionForward = new ActionForward(mapping.getInput());

            session.removeAttribute(getMasterFormSessionName());
            removeMasterMaintDelegate(session);
            actionForward = mapping.findForward("default");

            if (getKeepSearchResult()) {
                session.setAttribute(getSessionReset(), GENERIC_YES);
            }

            if (getNeedSetGotoURL()) {
                form.setGotoURL(actionForward.getPath());
            }
            //cleanup(mapping, formIn, request, response, errors);
        } catch (Exception e) {
            errors.add(ActionErrors.GLOBAL_ERROR, new ActionError("exception.error", e.getMessage()));
            Logger.logExceptions(this, e);
        }
        return actionForward;
    }
    
    protected ActionForward processActionChangeFolder(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response, ActionErrors errors) {

        ActionForward actionForward = null;
        try {
            SimpleMaintStyleForm form = (SimpleMaintStyleForm) formIn;
            actionForward = new ActionForward(mapping.getInput());

            String[] folderChild = getFolderChildIdxMapping();
            if (folderChild != null) {
                int newFolderIdx = Integer.parseInt(form.getPageEventSrc());

                form.setFolderIdx(String.valueOf(newFolderIdx));

                try{
                    int curIdx = Integer.parseInt(folderChild[newFolderIdx]);
                    form.setCurrIdx(curIdx);
                } catch(Exception e){
                    form.setCurrIdx(0);
                }
            }
        } catch (Exception e) {
            errors.add(ActionErrors.GLOBAL_ERROR, new ActionError("exception.error", e.getMessage()));
            Logger.logExceptions(this, e);
        }

        return actionForward;
    }
    
    protected ActionForward processActionCreate(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response, ActionErrors errors) {

        ActionForward actionForward = null;
        try {
            SimpleMaintStyleForm form = (SimpleMaintStyleForm) formIn;
            HttpSession session = request.getSession(false);

            actionForward = new ActionForward(mapping.getInput());

            User editingUser = (User) session.getAttribute(SimpleConstants.SESSION_USER);

            SimpleBaseVo model = getInitialzedModel(form, editingUser);
            if (model != null) {
                session.setAttribute(getSessionSimpleMaintInitModel(), model);
            }
            session.setAttribute(getSessionSimpleMaintStatus(), "create");
            actionForward = mapping.findForward("reload");
        } catch (Exception e) {
            errors.add(ActionErrors.GLOBAL_ERROR, new ActionError("exception.error", e.getMessage()));
            Logger.logExceptions(this, e);
        }
        return actionForward;
    }
    
    protected ActionForward processStatusCreate(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response, ActionErrors errors, String rb_status) {

        ActionForward actionForward = null;
        try {
            SimpleMaintStyleForm form = (SimpleMaintStyleForm) formIn;
            HttpSession session = request.getSession(false);

            actionForward = new ActionForward(mapping.getInput());

            ArrayList menuObjectList = form.getMenuObjectList();
            form = (SimpleMaintStyleForm) this.createMasterForm(mapping, form, request, response, errors);

            // 1. remove old MasterDelegate from session
            removeMasterMaintDelegate(session);

            // 2. get pre-initialized model, if any
            SimpleBaseVo initializedModel = (SimpleBaseVo) session.getAttribute(getSessionSimpleMaintInitModel());
            session.removeAttribute(getSessionSimpleMaintInitModel());

            if (initializedModel != null) {
                beforeModelToForm(mapping, form, request, response, errors, initializedModel);
                modelToForm(initializedModel, form);
                afterModelToForm(mapping, form, request, response, errors, initializedModel);
            }

            form.setMenuObjectList(menuObjectList);
            
            initPage(mapping, form, request, response, errors);
            form.setPageMode("create");
            beforeCreate(mapping, form, request, response, errors);
            super.copyTsFromVoToForm(mapping, form, request, response, null);
            session.setAttribute(getMasterFormSessionName(), form);
            this.afterProcessStatusCreate(mapping, form, request, response, errors, rb_status);
        } catch (Exception e) {
            errors.add(ActionErrors.GLOBAL_ERROR, new ActionError("exception.error", e.getMessage()));
            Logger.logExceptions(this, e);
        }

        return actionForward;
    }

    protected void afterProcessStatusCreate(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response, ActionErrors errors, String rb_status) {
        // NOOP
    }

    protected ActionForward processActionDelete(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response, ActionErrors errors, boolean deleteForever) {

        ActionForward actionForward = null;
        try {
            beforeDelete(mapping, formIn, request, response, errors);
            SimpleMaintStyleForm form = (SimpleMaintStyleForm) formIn;
            HttpSession session = request.getSession(false);

            actionForward = new ActionForward(mapping.getInput());

            SimpleSearchMaintStyleDelegate dg = getMasterMaintDelegate(session);

            SimpleBaseVo model = (SimpleBaseVo) form.getOldValues();

            Logger.debug(this, "processActionDelete(), deleting : " + model);

            if (model != null) {
                if (canDel(formIn, request, errors)) {
                    SimpleBasePk pk = (SimpleBasePk) model.getPrimaryKey();
                    model.setDeleteForever(deleteForever);
                    dg.removeMaster(model, pk);

                    session.setAttribute(getSessionAlertAfterDelete(), GENERIC_YES);
                    actionForward = mapping.findForward("search");
                }
            }
            afterDelete(mapping, formIn, request, response, errors);
        } catch (Exception e) {
            errors.add(ActionErrors.GLOBAL_ERROR, new ActionError("exception.error", e.getMessage()));
            Logger.logExceptions(this, e);
        }

        return actionForward;
    }
    
    protected ActionForward processActionEdit(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response, ActionErrors errors) {

        ActionForward actionForward = null;
        try {
            SimpleMaintStyleForm form = (SimpleMaintStyleForm) formIn;
            HttpSession session = request.getSession(false);
            actionForward = new ActionForward(mapping.getInput());

            SimpleBasePk pk = getPk(formIn, request);
            if(pk != null) {
                session.setAttribute(getSessionSimpleMaintPk(), pk);
                session.setAttribute(getSessionSimpleMaintEditType(), form.getEditType());
                processStatusEdit(mapping, formIn, request, response, errors, STATUS_EDIT);
                actionForward = new ActionForward(mapping.getInput());
            } else {
                actionForward = mapping.findForward("error");
            }
            
        } catch (Exception e) {
            errors.add(ActionErrors.GLOBAL_ERROR, new ActionError("exception.error", e.getMessage()));
            Logger.logExceptions(this, e);
        }
        return actionForward;
    }
    
    protected ActionForward processStatusEdit(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response, ActionErrors errors, String rb_status) {

        ActionForward actionForward = null;
        try {            
            SimpleMaintStyleForm form = (SimpleMaintStyleForm) formIn;
            beforeEdit(mapping, form, request, response, errors);
            
            HttpSession session = request.getSession(false);
            actionForward = new ActionForward(mapping.getInput());
            SimpleBasePk pk = (SimpleBasePk) session.getAttribute(getSessionSimpleMaintPk());
            session.removeAttribute(getSessionSimpleMaintPk());
            User editingUser = (User) session.getAttribute(SimpleConstants.SESSION_USER);
            
            Logger.debug(this, "processStatusEdit(), PK is null?" + (pk));
            Logger.debug(this, "processStatusEdit(), getMasterFormClass is null?" + (getMasterFormClass() == null));
            Logger.debug(this, "processStatusEdit(), editingUser is null?" + (editingUser == null));

            ArrayList menuObjectList = form.getMenuObjectList();
            form = (SimpleMaintStyleForm) this.createMasterForm(mapping, form, request, response, errors);

            // 1. remove old MasterDelegate from session
            removeMasterMaintDelegate(session);

            // 2. create new MasterDelegate
            SimpleSearchMaintStyleDelegate dg = getMasterMaintDelegate(session);

            // 3. retrieve the model
            SimpleBaseVo dummy = (SimpleBaseVo) getMasterVOClass().newInstance();
            SimpleBaseVo model = dg.findByPrimaryKey(dummy, pk);
            if (model == null) {
                throw new Exception("No record found: " + pk);
            }

            model.setIsExisting(true);

            form.setOldValues(model);
            form.setEditType((String) session.getAttribute(getSessionSimpleMaintEditType()));
            beforeModelToForm(mapping, formIn, request, response, errors, model);
            modelToForm(model, form);
            afterModelToForm(mapping, formIn, request, response, errors, model);
            form.setMenuObjectList(menuObjectList);

            initPage(mapping, form, request, response, errors);
            form.setPageMode("modify");
            //loadDefaults(mapping, form, request, response);
            afterEdit(mapping, form, request, response, errors);
            
            super.copyTsFromVoToForm(mapping, form, request, response, model);
            session.setAttribute(getMasterFormSessionName(), form);
            
        } catch (Exception e) {
            errors.add(ActionErrors.GLOBAL_ERROR, new ActionError("exception.error", e.getMessage()));
            Logger.logExceptions(this, e);
        }

        return actionForward;
    }
    
    protected ActionForward processActionRefresh(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response, ActionErrors errors) {

        ActionForward actionForward = null;
        try {
            SimpleMaintStyleForm form = (SimpleMaintStyleForm) formIn;
            HttpSession session = request.getSession(false);
            actionForward = new ActionForward(mapping.getInput());
            ArrayList menuObjectList = form.getMenuObjectList();

            beforeRefresh(mapping, formIn, request, response, errors);

            form = (SimpleMaintStyleForm) this.createMasterForm(mapping, form, request, response, errors);

            // 1. remove old MasterDelegate from session
            removeMasterMaintDelegate(session);

            // 2. create new MasterDelegate
            SimpleSearchMaintStyleDelegate dg = getMasterMaintDelegate(session);

            // 3. retrieve the model
            SimpleBaseVo dummy = (SimpleBaseVo) getMasterVOClass().newInstance();

            SimpleBasePk pk = getPk(formIn, request);

            SimpleBaseVo model = (SimpleBaseVo) dg.findByPrimaryKey(dummy, pk);
            if (model == null) {
                throw new Exception("No record found: " + pk);
            }

            model.setIsExisting(true);

            form.setOldValues(model);
            beforeModelToForm(mapping, formIn, request, response, errors, model);
            modelToForm(model, form);
            afterModelToForm(mapping, formIn, request, response, errors, model);
            form.setEditType(((SimpleMaintStyleForm) formIn).getEditType());
            form.setMenuObjectList(menuObjectList);

            initPage(mapping, form, request, response, errors);
            //loadDefaults(mapping, form, request, response);

            form.setPageEventSrc(((SimpleMaintStyleForm) formIn).getFolderIdx());
            form.setFolderIdx(((SimpleMaintStyleForm) formIn).getFolderIdx());
            form.setCurrIdx(((SimpleMaintStyleForm) formIn).getCurrIdx());

            processActionChangeFolder(mapping, form, request, response, errors);

            form.setPageMode("modify");

            super.copyTsFromVoToForm(mapping, form, request, response, model);
            session.setAttribute(getMasterFormSessionName(), form);
            
            afterRefresh(mapping, formIn, request, response, errors);
        } catch (Exception e) {
            errors.add(ActionErrors.GLOBAL_ERROR, new ActionError("exception.error", e.getMessage()));
            Logger.logExceptions(this, e);
        }

        return actionForward;
    }
    
    protected String getSearchPath(ActionForm formIn) {
    	return null;
    }
    
    
    protected ActionForward processActionSearch(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response, ActionErrors errors) {
		String path = getSearchPath(formIn);
		if (CommonUtil.isEmpty(path)) {
			path = "search";
		}
		return mapping.findForward(path);
    }
    
    protected ActionForward processActionBack(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse resopnse, ActionErrors errors) {
        ActionForward actionForward = null;
        SimpleMaintStyleForm form = (SimpleMaintStyleForm) formIn;
        String backTo = form.getBackTo();

        actionForward = mapping.findForward(backTo);

        return actionForward;
    }

    protected ActionForward processActionCopy(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response, ActionErrors errors) {

        ActionForward actionForward = null;
        try {
            actionForward = new ActionForward(mapping.getInput());
            HttpSession session = request.getSession(false);
            SimpleMaintStyleForm form = (SimpleMaintStyleForm) formIn;
            SimpleBaseVo model = (SimpleBaseVo) form.getOldValues();
            SimpleBaseVo copiedModel = (SimpleBaseVo) CopyUtil.copy(model);
            SimpleBasePk pk = (SimpleBasePk) model.getPrimaryKey();
            stripModelPrimaryKey(copiedModel, pk);
            stripFields(copiedModel);
            copyModelChildren(copiedModel, model);
            copiedModel.setIsExisting(false);
            processPostCopy(copiedModel, session, errors);

            if (errors.size() > 0)
                return actionForward;

            session.setAttribute(getSessionSimpleMaintInitModel(), copiedModel);
            session.setAttribute(getSessionSimpleMaintStatus(), "create");
            request.setAttribute(AFTER_COPY_ACTION, GENERIC_YES);
            actionForward = mapping.findForward("reload");
        } catch (Exception e) {
            errors.add(ActionErrors.GLOBAL_ERROR, new ActionError("exception.error", e.getMessage()));
            Logger.logExceptions(this, e);
        }

        return actionForward;
    }

    protected ActionForward processStatusCopy(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response, ActionErrors errors, String rb_status) {

        ActionForward actionForward = null;
        try {
            SimpleMaintStyleForm form = (SimpleMaintStyleForm) formIn;
            HttpSession session = request.getSession(false);
            actionForward = new ActionForward(mapping.getInput());
            SimpleMaintStyleForm tmpForm = (SimpleMaintStyleForm) formIn;

            removeMasterMaintDelegate(session);

            form = (SimpleMaintStyleForm) this.createMasterForm(mapping, form, request, response, errors);
            form.setMenuObjectList(tmpForm.getMenuObjectList());

            HashMap params = (HashMap) session.getAttribute(SimpleConstants.SESSION_COMMON_SEARCH_PARAMETERS);
            session.removeAttribute(SimpleConstants.SESSION_COMMON_SEARCH_PARAMETERS);

            populateForm(form, params, request);
            session.setAttribute(getMasterFormSessionName(), form);

        } catch (Exception e) {
            errors.add(ActionErrors.GLOBAL_ERROR, new ActionError("exception.error", e.getMessage()));
            Logger.logExceptions(this, e);
        }

        return actionForward;

    }

    protected ActionForward processActionSave(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response, ActionErrors errors) {

        ActionForward actionForward = null;
        try {
            HttpSession session = request.getSession(false);
            SimpleMaintStyleForm form = (SimpleMaintStyleForm) formIn;
            actionForward = new ActionForward(mapping.getInput());
            User editingUser = (User) session.getAttribute(SimpleConstants.SESSION_USER);
            beforeSave(mapping, formIn, request, response, errors);
            
//            if (CHECK_TOKEN) {
//                if (!isTokenValid(request)) {
//                    errors
//                            .add(
//                                    ActionErrors.GLOBAL_ERROR,
//                                    new ActionError(
//                                            "error.msg",
//                                            "You may press the back button and then save this page! Please try to retrieve the data again and then change accordingly for saving!"));
//                    saveErrors(request, errors);
//                    saveToken(request);
//                    return actionForward;
//                }
//            }

            //beforeValidate(mapping, formIn, request, response, errors);
            form.validate(errors);
            otherValidate(mapping, formIn, request, response, errors);
            form.moreValidate(mapping, formIn, request, response, errors);

            if (errors.size() == 0) {
                SimpleBaseVo model = (SimpleBaseVo) getMasterVOClass().newInstance();

                beforeFormToModel(mapping, formIn, request, response, errors, model);
                formToModel(form, model);
                afterFormToModel(mapping, formIn, request, response, errors, model);
                validateInput(errors, model);

                // save the model data
                if (errors.size() == 0) {

                    SimpleBaseVo originalModel = (SimpleBaseVo) form.getOldValues();
                    model.setOldModel(originalModel);
                    boolean modified = filterForEdited(model, originalModel, editingUser);
                    SimpleBasePk pk = null;

                    if (modified) {
                        if (CHECK_VERSION) {
                            setLastModifiedTime(model);
                        }

                        if (model.checkFieldLength()) {
                            SimpleSearchMaintStyleDelegate dg = getMasterMaintDelegate(session);
                            if (form.getPageMode().equals("create")) {
                                pk = dg.createMaster(model);
                            } else {
                                dg.updateMaster(model);
                                pk = (SimpleBasePk) model.getPrimaryKey();
                            }
                        }
                    }

                    session.setAttribute(getSessionAlertAfterSave(), GENERIC_YES);

                    form.setPageMode("modify");
                    session.setAttribute(getSessionSimpleMaintStatus(), "saved-edit");

                    Logger.debug(this, "processActionSave(), pk = [" + pk + "]");

                    session.setAttribute(getSessionSimpleMaintPk(), pk);
                    setSessionFolderIdx(mapping, formIn, request, response);
                    actionForward = mapping.findForward("reload");
                }
                afterSave(mapping, formIn, request, response, errors);
            }
        } catch (Exception e) {
//            boolean starts_with_li = e.getMessage().startsWith("<li>");
//            String errMsg = e.getMessage();
//            String newErrMsg = "";
//            if (errMsg.indexOf("ORA-00001") > -1) {
//            	newErrMsg = "Duplicate entry in database";
//            }
//            
//            if(CommonUtil.isEmpty(newErrMsg)){
//            	errors.add(ActionErrors.GLOBAL_ERROR, new ActionError(starts_with_li ? "error.msg" : "exception.error", e
//						.getMessage()));
//            } else {
//            	errors.add(ActionErrors.GLOBAL_ERROR,
//						new ActionError(starts_with_li ? "error.msg" : "exception.error", newErrMsg));
//            }
        	errors.add(ActionErrors.GLOBAL_ERROR, new ActionError("error.msg", e
					.getMessage()));
            Logger.logExceptions(this, e);
        }

        return actionForward;
    }

    protected SimpleSearchMaintStyleDelegate getMasterMaintDelegate(HttpSession session) {

        SimpleSearchMaintStyleDelegate masterDg = null;
        try {
            Class masterClass = getMasterDelegateClass();
            masterDg = (SimpleSearchMaintStyleDelegate) session.getAttribute(getSessionMasterMaintDelegate());
            if (masterDg != null) {
                Logger.all(this, "getMasterMaintDelegate(), masterDg.getClass().getName()=[" + masterDg.getClass().getName()
                        + "]");
                Logger.all(this, "getMasterMaintDelegate(), masterClass.getName()=[" + masterClass.getName() + "]");

                if (masterDg.getClass().getName().equals(masterClass.getName())) {
                    return masterDg;
                } else {
                    masterDg = (SimpleSearchMaintStyleDelegate) getMasterDelegateClass().newInstance();

                    session.setAttribute(getSessionMasterMaintDelegate(), masterDg);
                    return masterDg;
                }
            } else {
                masterDg = (SimpleSearchMaintStyleDelegate) getMasterDelegateClass().newInstance();

                session.setAttribute(getSessionMasterMaintDelegate(), masterDg);
                return masterDg;
            }
        } catch (Exception e) {
            Logger.logExceptions(this, e);
        }
        return null;
    }

    protected void removeMasterMaintDelegate(HttpSession session) {

        try {
            getMasterMaintDelegate(session).removeSessionBean();
            session.removeAttribute(getSessionMasterMaintDelegate());
        } catch (Exception e) {
            Logger.logExceptions(this, e);
        }
    }
    
    protected String getSessionAlertAfterSave() {

        return SimpleConstants.SESSION_ALERT_AFTER_SAVE;
    }

    protected String getSessionAlertAfterDelete() {

        return SimpleConstants.SESSION_ALERT_AFTER_DELETE;
    }

    protected String getSessionFolderIdx() {

        return SimpleConstants.SESSION_SIMPLE_MAIN_FOLDER_IDX;
    }

    protected void setSessionFolderIdx(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response) {

        try {
            HttpSession session = request.getSession(false);
            SimpleMaintStyleForm form = (SimpleMaintStyleForm) formIn;
            session.setAttribute(getSessionFolderIdx(), form.getFolderIdx());
        } catch (Exception e) {
            Logger.logExceptions(this, e);
        }
    }

    public void modelToForm(SimpleBaseVo model, SimpleMaintStyleForm form) {

        try {
            CopyUtil.convToStrObj(form, model);
            CopyUtil.copyByteArray(form, model);
            if (model.getIsExisting()) {
                form.setPageMode("modify");
            } else {
                form.setPageMode("create");
            }

            Class[] voChildClass = model.getChildTypes();
            Class[] rowClass = getChildRowClass();
            if( (voChildClass != null) && (rowClass != null)){
            	modelToRow(model, form);
            }

        } catch (Exception e) {
            Logger.logExceptions(this, e);
        }
    }

    public void modelToRow(SimpleBaseVo model, SimpleMaintStyleForm form) {
        int currIdx = 0;
        try {
            currIdx = form.getCurrIdx();
            Class[] rowClass = getChildRowClass();

            if (rowClass == null) {
                throw new NullValueException("rowClass is null or length is zero!");
            }

            Class[] voChildClass = model.getChildTypes();

            if (voChildClass == null) {
                throw new NullValueException("voChildClass is null or length is zero!");
            }

            if (rowClass.length != voChildClass.length) {
                throw new NotEqualException("rowClass and voChildClass length not equal!");
            }

            int count = rowClass.length;
            for (int i = 0; i < count; i++) {
                form.setCurrIdx(i);
                ChildList details = model.getChilds(voChildClass[i]);

                if (details == null)
                    continue;

                int detailCount = details.size();

                MultiRow row = null;

                for (int j = 0; j < detailCount; j++) {
                    row = (MultiRow) rowClass[i].newInstance();
                    SimpleBaseVo detail = (SimpleBaseVo) details.get(j);

                    CopyUtil.convToStrObj(row, detail);

                    modelToRowLoop(row, detail);

                    row.setIsDelete("");
                    row.setVisible(true);
                    row.setModeModify();
                    
                    if(!CommonUtil.isEmpty(detail.getTableSchemaName())){
                        try{
                            row.setTs((TableSchema)detail.getTableSchemaType().newInstance());
                            row.setTsName(detail.getTableSchemaName());
                        }catch(Exception e){
                            row.setTs(new TableSchema());
                            row.setTsName("");
                            throw new Exception("Model's table schema is null or empty");
                        }
                    }
                    form.setRow(j, row);
                }
            }

            modelToRowOther(model, form);

        } catch (Exception e) {
            Logger.logExceptions(this, e);
        } finally {
            form.setCurrIdx(currIdx);
        }
    }

    protected void modelToRowLoop(MultiRow row, SimpleBaseVo detail) throws IllegalAccessException, InvocationTargetException,
            NoSuchMethodException {
        CopyUtil.copyByteArray(row, detail);
    }

    protected void modelToRowOther(SimpleBaseVo model, SimpleMaintStyleForm form) {

    }

    public void formToModel(SimpleMaintStyleForm form, SimpleBaseVo model) {

        int currIdx = 0;
        try {
            currIdx = form.getCurrIdx();
            CopyUtil.cpNconv(model, form);
            CopyUtil.copyByteArray(model, form);
            model.setIsExisting(!form.getPageMode().equals("create"));

            Class[] rowClass = getChildRowClass();

            if (rowClass == null) {
                //throw new NullValueException("rowClass is null or length is zero!");
            	return;
            }

            Class[] voChildClass = model.getChildTypes();

            if (voChildClass == null) {
                //throw new NullValueException("voChildClass is null or length is zero!");
            	return;
            }

            if (rowClass.length != voChildClass.length) {
                throw new NotEqualException("rowClass and voChildClass length not equal!");
            }

            int count = rowClass.length;

            for (int i = 0; i < count; i++) {
                ChildList childList = model.getChilds(voChildClass[i]);
                form.setCurrIdx(i);
                ArrayList rows = form.getMultiRows(i);

                if (rows == null)
                    continue;

                int rowSize = rows.size();

                SimpleBaseVo detail = null;
                MultiRow row = null;

                for (int j = 0; j < rowSize; j++) {
                    row = (MultiRow) rows.get(j);
                    int rowIdx = Integer.parseInt(row.getIdx());

                    if (rowIdx > childList.size() - 1) {
                        detail = (SimpleBaseVo) voChildClass[i].newInstance();
                        rowToModel(form, row, detail);
                        rowToModelLoop(form, row, detail);
                        childList.add(detail);
                    } else {
                        detail = (SimpleBaseVo) childList.get(rowIdx);
                        rowToModel(form, row, detail);
                        rowToModelLoop(form, row, detail);
                        childList.set(rowIdx, detail);
                    }
                }

                if (childList != null)
                    model.storeChilds(childList);
            }
        } catch (Exception e) {
            Logger.logExceptions(this, e);
        } finally {
            form.setCurrIdx(currIdx);
        }
    }

    protected void rowToModelLoop(SimpleMaintStyleForm form, MultiRow row, SimpleBaseVo detail) {

    }
    
    protected void rowToModel(SimpleMaintStyleForm form, MultiRow row, SimpleBaseVo detail) {

        try {
            CopyUtil.cpNconv(detail, row);
            detail.setIsDelete(row.getIsDelete() != null && row.getIsDelete().length() > 0);
        } catch (Exception e) {
            Logger.logExceptions(this, e);
        }
    }

    protected boolean filterForEdited(SimpleBaseVo currentVO, SimpleBaseVo originalVO, User editingUser) throws Exception {

        boolean modified = false;
        try {
            if (currentVO != null) {

                java.sql.Timestamp now = new java.sql.Timestamp(System.currentTimeMillis());

                currentVO.setLastModifiedTime(currentVO.getUpdateDate());

                if (originalVO != null) {
                    originalVO.setLastModifiedTime(originalVO.getUpdateDate());
                }

                // compares the child first
                ArrayList childsList = currentVO.getChildsList();
                Iterator iterator = childsList.iterator();
                while (iterator.hasNext()) {
                    ChildList currentChildList = (ChildList) iterator.next();
                    Class childType = currentChildList.getChildType();

                    Iterator iterator2 = currentChildList.iterator();
                    while (iterator2.hasNext()) {

                        SimpleBaseVo currentChildVO = (SimpleBaseVo) iterator2.next();
                        SimpleBaseVo originalChildVO = null;

                        if (currentChildVO.getIsExisting()) {
                            originalChildVO = originalVO == null ? null : originalVO.getChildVO(currentChildVO.getPrimaryKey(),
                                    childType);
                        }
                        
//                        Logger.debug("filterForEdited(), currentChildVO..getClass().getName()=" + currentChildVO.getClass().getName());
//                        Logger.debug("filterForEdited(), currentChildVO.getPrimaryKey()=" + currentChildVO.getPrimaryKey());
                        // the (or) order must be in this order!!!
                        // don't revert the order
                        // if revert the filterForEdited will not be run if
                        // modified is true
                        modified = (this.filterForEdited(currentChildVO, originalChildVO, editingUser) || modified);

                        /**
                         * ***** this one is for debug only should remove this statement after debuggin ***
                         */
                        modified = true;
                    }
                }
                
//                Logger.field(this, "filterForEdited(), child modified? " + modified);
//                Logger.debug("filterForEdited(), originalVO.getClass().getName()=" + originalVO.getClass().getName());
//                Logger.debug("filterForEdited(), currentVO.getClass().getName()=" + currentVO.getClass().getName());

//                boolean isIdentical = BeanUtil.isIdentical(originalVO, currentVO);
                
//                Logger.debug("filterForEdited(), modified?" + (modified));
//                Logger.debug("filterForEdited(), originalVO=null?" + (originalVO == null));
//                Logger.debug("filterForEdited(), currentVO.getIsDelete()?" + (currentVO.getIsDelete()));
//                Logger.debug("filterForEdited(), isIdentical=?" + (isIdentical));
//                Logger.debug("filterForEdited(), currentVO.getIsExisting()=?" + currentVO.getIsExisting());
                
                // compares header
                if (modified || originalVO == null || currentVO.getIsDelete() || !BeanUtil.isIdentical(originalVO, currentVO)) {

                    modified = true;

                    if (!currentVO.getIsExisting()) {
                        currentVO.setCreateUser(editingUser.getUserId());
                    } else {
                        currentVO.setIsDirty(true);
                        currentVO.setUpdateUser(editingUser.getUserId());
                    }
                }
            }
        } catch (Exception e) {
            Logger.logExceptions(this, e);
            throw e;
        }

        return modified;
    }

    protected final void validateInput(ActionErrors errors, SimpleBaseVo model) throws Exception {

        if (model == null) {
            return;
        }

        try {
            SimpleSearchMaintStyleDelegate dg = new SimpleSearchMaintStyleDelegate();

            SimpleBasePk pk = (SimpleBasePk) model.getPrimaryKey();
            if (pk != null) {

                boolean isNew = !model.getIsExisting();
                boolean isDelete = model.getIsDelete();

                if (isDelete) {
                    // check for foreign key integrity, i.e.
                    // 1. the current record is going to be deleted
                    // 2. records in other tables reference the current record
//                    checkFKIntegrity(model, errors);
                } else {
                    // check for duplicate
                    if (isNew && dg.findByPrimaryKey(model, pk) != null) {
                        errors.add(ActionErrors.GLOBAL_ERROR, new ActionError("error.general.key.duplicate", pk));
                    }

                    // check for model validaty
//                    checkModel(model, errors);
                }
            }
        } catch (Exception e) {
            errors.add(ActionErrors.GLOBAL_ERROR, new ActionError("exception.error", e.getMessage()));
            Logger.logExceptions(this, e);
            throw e;
        }
    }

//    protected void checkFKIntegrity(SimpleBaseVo model, ActionErrors errors) {
//
//    }
//
//    protected void checkModel(SimpleBaseVo model, ActionErrors errors) {
//
//    }

    protected void setDefaultFolderIdx(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response, ActionErrors errors) {

        try {
            HttpSession session = request.getSession(false);
            SimpleMaintStyleForm form = (SimpleMaintStyleForm) formIn;

            String folderIdx = CommonUtil.nullToString((String) session.getAttribute(getSessionFolderIdx()));
            session.removeAttribute(getSessionFolderIdx());

            form.setPageEventSrc("0");

            if (!folderIdx.equals("")) {
                form.setPageEventSrc(folderIdx);
            }
        } catch (Exception e) {
            errors.add(ActionErrors.GLOBAL_ERROR, new ActionError("exception.error", e.getMessage()));
            Logger.logExceptions(this, e);
        }
    }

    protected boolean checkIfFormExists(SimpleBasePk pk, ActionErrors errors) throws Exception {

        boolean rslt = false;
        try {
            SimpleSearchMaintStyleDelegate dg = (SimpleSearchMaintStyleDelegate) getMasterDelegateClass().newInstance();
            rslt = dg.checkIfFormExists(pk);
        } catch (Exception e) {
            errors.add(ActionErrors.GLOBAL_ERROR, new ActionError("exception.error", e.getMessage()));
            Logger.logExceptions(this, e);
            throw e;
        }
        return rslt;
    }
    
    private void copyModelChildren(SimpleBaseVo dest, SimpleBaseVo orig) throws InstantiationException, IllegalAccessException,
            InvocationTargetException, NoSuchMethodException {
        Iterator childListIt = orig.getChildsList().iterator();
        Iterator childrenIt = null;

        while (childListIt.hasNext()) {
            ChildList oldList = (ChildList) childListIt.next();
            ChildList newList = new ChildList(oldList.getChildType());
            childrenIt = oldList.iterator(); // individual type of children

            while (childrenIt.hasNext()) {
                Object origChild = childrenIt.next();
                Object destChild = null;

                if (((SimpleBaseVo) origChild).isCopyable()) {
                    destChild = CopyUtil.copy(origChild);
                    stripFields((SimpleBaseVo) destChild);
                    ((SimpleBaseVo) destChild).setIsExisting(false);
                    newList.add(destChild);
                }
            }
            dest.storeChilds(newList);
        }
    }

    protected void stripModelPrimaryKey(SimpleBaseVo model, SimpleBasePk pk) throws IllegalAccessException,
            InvocationTargetException {
        PropertyDescriptor pkDescriptors[] = PropertyUtils.getPropertyDescriptors(pk);
        String name = "";
        for (int i = 0; i < pkDescriptors.length; i++) {
            name = pkDescriptors[i].getName();
            try {
                if (name.equals("class"))
                    continue;
                PropertyUtils.setSimpleProperty(model, name, null);
            } catch (NoSuchMethodException e) {
            }
        }

    }

    protected void stripFields(SimpleBaseVo model) throws IllegalAccessException, InvocationTargetException,
            NoSuchMethodException {
        Collection list = model.getStrippableFields();
        PropertyDescriptor propertyDescriptor = null;
        PropertyDescriptor propertyDescriptors[] = PropertyUtils.getPropertyDescriptors(model);
        Iterator it = list.iterator();
        String fieldName = "";
        String name = "";

        while (it.hasNext()) {
            fieldName = (String) it.next();
            for (int i = 0; i < propertyDescriptors.length; i++) {
                propertyDescriptor = propertyDescriptors[i];
                name = propertyDescriptor.getName();

                if (fieldName.equals(name)) {
                    PropertyUtils.setSimpleProperty(model, name, null);
                    break;
                }
            }
        }

    }
  
    protected boolean canDel(ActionForm formIn, HttpServletRequest request, ActionErrors errors) {

        return true;
    }

    protected void setAccessControl(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response, ActionErrors errors) {

    }

    protected void setLastModifiedTime(SimpleBaseVo currentVO) {

        try {
            ChildList child = null;
            Iterator itr = null;

            currentVO.setLastModifiedTime(currentVO.getUpdateDate());

            Class[] voChildClass = currentVO.getChildTypes();

            if (voChildClass == null) {
                return;
            }

            int counter = voChildClass.length;
            for (int i = 0; i < counter; i++) {
                child = currentVO.getChilds(voChildClass[i]);
                if (child == null)
                    continue;

                itr = child.iterator();
                while (itr.hasNext()) {
                    SimpleBaseVo vo = (SimpleBaseVo) itr.next();
                    if (vo == null)
                        continue;
                    vo.setLastModifiedTime(vo.getUpdateDate());
                }
            }
        } catch (Exception e) {
            Logger.error(this, "processActionChangeFolder(), error: " + e.getMessage());
            Logger.logExceptions(this, e);
        }
    }

    private void populateIsDelete(ActionForm formIn, HttpServletRequest request) {
        SimpleMaintStyleForm form = (SimpleMaintStyleForm) formIn;
        String[] isDelete = request.getParameterValues("isDelete");
        String[] idx = request.getParameterValues("idx");
        if (isDelete == null) {
            form.setIsDelete(isDelete);
        }
        if (idx == null) {
            form.setIdx(idx);
        }
    }
    
    private void processRequestAttributes(ActionForm formIn, HttpServletRequest request) {
        SimpleCoreForm form = (SimpleCoreForm) formIn;

        if (!CommonUtil.isEmpty((String) request.getAttribute(REQUEST_ATTRIB_KEY_READONLY))) {
            form.setIsReadOnly(GENERIC_YES);
            request.removeAttribute(REQUEST_ATTRIB_KEY_READONLY);
        }

        if (!CommonUtil.isEmpty((String) request.getAttribute(REQUEST_ATTRIB_KEY_BACK_TO))) {
            form.setBackTo((String) request.getAttribute(REQUEST_ATTRIB_KEY_BACK_TO));
            request.removeAttribute(REQUEST_ATTRIB_KEY_BACK_TO);
        }
    }

    protected boolean hasAccessRight(String menuId, User editingUser) {

        boolean hasRight = true;
        return hasRight;
    }
    
    ////////////////////////////////////////////////////////////////////////////////
    // END OF LOGICAL AND BUSINESS METHODS
    ////////////////////////////////////////////////////////////////////////////////
    
}